/* 
* 版权所有 2015 魔视智能科技(上海)有限公司
* Copyright (c) 2015,Motovis Intelligent Technologies (Shanghai) Co.,Ltd
* 魔视智能公司秘密
* Motovis Intelligent Confidential Proprietary
* 文件名称：update.h
* 摘要: 系统升级头文件
* 版本: V1.0.0.0
* 作者: zhangwenjian
* 完成日期: 2018年3月3日
* 历史记录：
*/

#include "common.h"

static PartInfo aPartDefinition[PART_MAX_NUM];
static pthread_mutex_t *g_pMutexOta = NULL;
static pthread_mutex_t *g_pMutexRqs = NULL;
static char requestValve = RQS_OTA_NONE;
static char otaState = E_OTAUpgradeStatusInit;

int ReadMMCInfo()
{
	FILE *pFp = NULL;
	char szLine[256];
	char chDeviceName[16] = {0};
	char chDeviceLabel[16] = {0};
	int nId = 0;
	int nIndex = 0;
	int nSscanfNum = 0;
	unsigned long nMajor = 0;
	unsigned long nMinor = 0;
	unsigned long nBlocks = 0;
	static int nHaveReadFlag = 0;

	if (nHaveReadFlag == 1)
	{
		return 0;
	}

	pFp = fopen("/proc/partitions", "r");
	if (pFp == NULL) 
	{
		DEBUG("open /proc/partitions failed\n");
		return -1;
	}	

	memset(szLine, 0 , 256);
	while (fgets(szLine, 256, pFp))
	{
		memset(chDeviceName, 0 , 16);
		memset(chDeviceLabel, 0 , 16);
		nSscanfNum = sscanf(szLine ," %lu %lu %lu %s %s",&nMajor,&nMinor,&nBlocks,chDeviceName, chDeviceLabel);
		if (strncmp(chDeviceName, "mmcblk0p", 8) == 0 && nSscanfNum == 5)
		{
			sscanf(chDeviceName, "mmcblk0p%d:", &nId);
			sprintf(aPartDefinition[nIndex].szPartMMCBlockDev, "/dev/mmcblk0p%d", nId);
			aPartDefinition[nIndex].nPartLength = nBlocks;
			strncpy(aPartDefinition[nIndex].szPartLabel, chDeviceLabel, strlen(chDeviceLabel));
			++nIndex;	
		}
		memset(szLine, 0, 256);
	}
	fclose(pFp);

	nHaveReadFlag = 1;

#if 0
	printf("part_name   part_mmcblock_dev   part_size\n");
	for (nIndex = 0; nIndex < nId; nIndex++)
	{
		printf("%-10s %-20s 0x%08x\n", aPartDefinition[nIndex].szPartLabel, \
			aPartDefinition[nIndex].szPartMMCBlockDev, aPartDefinition[nIndex].nPartLength);
	}
#endif
	return 0;
}

int GetSDStatus(void)
{
	FILE *fstream = NULL;
	static int nSDStatus = 0;
	char cmd[100] = "df | awk '{if($6==\"/run/media/mmcblk1p1\"){print $1}}'";
	char buff[100];

	if(nSDStatus == SD_CARD_MOUNTED || nSDStatus == SD_CARD_UNMOUNTED)
		return  nSDStatus;

	memset(buff,0,sizeof(buff));
	if(NULL == (fstream = popen(cmd,"r"))) 
	{
		printf("popen error!\n");
		return -1;
	}
	if(NULL != fgets(buff, sizeof(buff), fstream))
	{
		printf("%s",buff);
	}
	else
	{
		pclose(fstream);
		return -1;
	}  
	pclose(fstream);

	if (strncmp(buff, "/dev/mmcblk1p1", 14) == 0)
	{
		nSDStatus =  SD_CARD_MOUNTED;
	}
	else
	{
		nSDStatus =  SD_CARD_UNMOUNTED;
	}

	return nSDStatus;
}

int IsSdBurnMode()
{
	if ((GetSDStatus() == SD_CARD_MOUNTED) && (access("/mnt/update.tar.gz", 0) != -1))
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

PartInfo *ReadInfo(  const char *pPartName)
{
	int nPartNo = 0;
	for (nPartNo = 0; nPartNo < PART_MAX_NUM; nPartNo++) 
	{
		if (strncmp(aPartDefinition[nPartNo].szPartLabel, pPartName, strlen(aPartDefinition[nPartNo].szPartLabel)) == 0)
			break;
	}
	if (nPartNo == PART_MAX_NUM) 
	{
		return NULL;
	}
	else
	{
		return &aPartDefinition[nPartNo];
	}
}

unsigned int GetZipFileSize(const char *pFileName)
{
	unsigned int nRet = 0;
	int nFileFd = -1;
	struct stat f_stat;

	if (pFileName == NULL) {
		nRet = 0;
		DEBUG("%s:%d pFileName is null\n", __func__, __LINE__);
		goto exit;
	}
	if (access(pFileName, R_OK) < 0) {
		nRet = 0;
		DEBUG("%s:%d pFileName:%s is not exist \n", __func__, __LINE__, pFileName);
		goto exit;
	}

	if ((nFileFd = open(pFileName, O_RDONLY)) < 0) {
		nRet = 0;
		DEBUG("%s:%d pFileName:%s open fail \n", __func__, __LINE__, pFileName);
		goto exit;
	}

	if ((fstat(nFileFd, &f_stat)) < 0) {
		nRet = 0;
		DEBUG("%s:%d pFileName:%s fstat run fail \n", __func__, __LINE__, pFileName);
		goto exit;
	}
	nRet = (unsigned int)f_stat.st_size;

exit:
	if (nFileFd != -1) {
		close(nFileFd);
	}
	return nRet;
}

int UpdateToPart(const char *pFileName, const char *pPartName)
{
	int nRet = 0;
	int nFileFd = -1, nMmcFd = -1;
	int nFileSize = 0, nFileLen = 0, nOffSet = 0;
	struct stat f_stat;
	char *pData = NULL;
	char *pTmpData = NULL;
	int nPartNo = 0;
	int nTryCount = 3;

	for (nPartNo = 0; nPartNo < PART_MAX_NUM; nPartNo++) 
	{
		if (strncmp(aPartDefinition[nPartNo].szPartLabel, pPartName, strlen(aPartDefinition[nPartNo].szPartLabel)) == 0)
			break;
	}
	if (nPartNo == PART_MAX_NUM) 
	{
		nRet = -1;
		goto exit;
	}

	if (pFileName == NULL) 
	{
		nRet = -2;
		goto exit;
	}
	if (access(pFileName, R_OK) < 0) 
	{
		nRet = -3;
		goto exit;
	}
	if ((nFileFd = open(pFileName, O_RDONLY)) < 0) 
	{
		nRet = -4;
		goto exit;
	}
	if ((nMmcFd = open(aPartDefinition[nPartNo].szPartMMCBlockDev, O_RDWR)) < 0) 
	{
		nRet = -5;
		goto exit;
	}
	if ((pData = (char *)malloc(EVERY_WRITE_LEN)) == NULL) 
	{
		nRet = -6;
		goto exit;
	}
	if ((pTmpData = (char *)malloc(EVERY_WRITE_LEN)) == NULL) 
	{
		nRet = -7;
		goto exit;
	}
	if ((fstat(nFileFd, &f_stat)) < 0) 
	{
		nRet = -8;
		goto exit;
	}
	nFileSize = (int)f_stat.st_size;
	if ((nFileSize>>10) > aPartDefinition[nPartNo].nPartLength) 
	{
		nRet = -9;
		goto exit;
	}
	while (nFileSize > 0) 
	{
		memset(pData, 0, EVERY_WRITE_LEN);
		nFileLen = EVERY_WRITE_LEN;
		if (nFileSize < nFileLen)
			nFileLen = nFileSize;
		if (read(nFileFd, pData, nFileLen) != nFileLen) 
		{
			nRet = -10;
			goto exit;
		}
again:
		if (write(nMmcFd, pData, nFileLen) != nFileLen) 
		{
			nRet = -11;
			goto exit;
		}
		lseek(nMmcFd, nOffSet, SEEK_SET);
		memset(pTmpData, 0, EVERY_WRITE_LEN);
		if (read(nMmcFd, pTmpData, nFileLen) != nFileLen) 
		{
			nRet = -12;
			goto exit;
		}
		if (memcmp((const void *)pData, (const void *)pTmpData, nFileLen) != 0) 
		{
			DEBUG("%s:%d write data error try again!\n", __func__, __LINE__);
			lseek(nMmcFd, nOffSet, SEEK_SET);
			if (nTryCount == 0)
			{
				nRet = -13;
				goto exit;
			}
			else
			{
				nTryCount--;
				goto again;
			}
		}
		nFileSize -= nFileLen;
		nOffSet += nFileLen;
	}

exit:
	if (nFileFd != -1)
		close(nFileFd);
	if (nMmcFd != -1)
		close(nMmcFd);
	if (pData != NULL)
		free(pData);
	if (pTmpData != NULL)
		free(pTmpData);

	if (nRet != 0) 
	{
		DEBUG("%s:%d write file:%s to part:%s failed, ret:%d\n",  \
			__func__, __LINE__, pFileName, pPartName, nRet);
	} 
	else 
	{
		DEBUG("write file:%s to part:%s finished\n", pFileName, pPartName);
	}
	return nRet;
}

int CopyPartToPart(const char *pSrcPartName, const char *pDstPartName)
{
	int nRet = 0;
	int nSrcMtdFd = -1, nDstMtdFd = -1;
	int nFileSize = 0, nFileLen = 0, nOffSet = 0;
	char *pData = NULL;
	char *pTmpData = NULL;
	int nIndex = 0;
	int nSrcPartNo = -1;
	int nDstPartNo = -1;
	int nTryCount = 3;

	for (nIndex = 0; nIndex < PART_MAX_NUM; nIndex++) 
	{
		if (strcmp(aPartDefinition[nIndex].szPartLabel, pSrcPartName) == 0)
		{
			nSrcPartNo = nIndex;
		}

		if (strcmp(aPartDefinition[nIndex].szPartLabel, pDstPartName) == 0)
		{
			nDstPartNo = nIndex;
		}
	}
	if ((nSrcPartNo == -1) || (nDstPartNo == -1) || \
		(aPartDefinition[nSrcPartNo].nPartLength != aPartDefinition[nDstPartNo].nPartLength)) 
	{
		nRet = -1;
		goto exit;
	}

	if ((nSrcMtdFd = open(aPartDefinition[nSrcPartNo].szPartMMCBlockDev, O_RDWR)) < 0) 
	{
		nRet = -2;
		goto exit;
	}
	
	if ((nDstMtdFd = open(aPartDefinition[nDstPartNo].szPartMMCBlockDev, O_RDWR)) < 0) 
	{
		nRet = -3;
		goto exit;
	}
	
	if ((pData = (char *)malloc(EVERY_WRITE_LEN)) == NULL) 
	{
		nRet = -4;
		goto exit;
	}
	
	if ((pTmpData = (char *)malloc(EVERY_WRITE_LEN)) == NULL) 
	{
		nRet = -5;
		goto exit;
	}
	nFileSize = aPartDefinition[nSrcPartNo].nPartLength;
	while (nFileSize > 0) 
	{
		memset(pData, 0, EVERY_WRITE_LEN);
		nFileLen = EVERY_WRITE_LEN;
		if (nFileSize < nFileLen)
			nFileLen = nFileSize;
		if (read(nSrcMtdFd, pData, nFileLen) != nFileLen) 
		{
			nRet = -6;
			goto exit;
		}
again:
		if (write(nDstMtdFd, pData, nFileLen) != nFileLen) 
		{
			nRet = -7;
			goto exit;
		}
		lseek(nDstMtdFd, nOffSet, SEEK_SET);
		memset(pTmpData, 0, EVERY_WRITE_LEN);
		if (read(nDstMtdFd, pTmpData, nFileLen) != nFileLen) 
		{
			nRet = -8;
			goto exit;
		}
		if (memcmp((const void *)pData, (const void *)pTmpData, nFileLen) != 0) 
		{
			DEBUG("%s:%d write data error try again!\n", __func__, __LINE__);
			lseek(nDstMtdFd, nOffSet, SEEK_SET);
			if (nTryCount == 0)
			{
				nRet = -9;
				goto exit;
			}
			else
			{
				nTryCount--;
				goto again;
			}
		}
		nFileSize -= nFileLen;
		nOffSet += nFileLen;
	}

exit:
	if (nSrcMtdFd != -1)
		close(nSrcMtdFd);
	if (nDstMtdFd != -1)
		close(nDstMtdFd);
	if (pData != NULL)
		free(pData);
	if (pTmpData != NULL)
		free(pTmpData);

	if (nRet != 0) 
	{
		DEBUG("%s:%d copy src part:%s to dst part:%s failed, ret:%d\n",  \
			__func__, __LINE__, pSrcPartName, pDstPartName, nRet);
	} 
	else 
	{
		DEBUG("copy src part:%s to dst part:%s finished\n", pSrcPartName, pDstPartName);
	}
	return nRet;
}

int CopyFileToFile(const char *pSrcFile, const char *pDstFile)
{
	int nRet = 0;
	FILE *pSrcFp = NULL;
	FILE *pDstFp = NULL;
	unsigned int nReadLen = 0;
	unsigned int nWriteLen = 0;
	char szTmpBuf[EVERY_WRITE_LEN];
	 
	pSrcFp = fopen(pSrcFile, "r");
	if (pSrcFp == NULL)
	{
		nRet = -1;
		goto exit;
	}

	pDstFp = fopen(pDstFile, "w+");
	if (pDstFp == NULL)
	{
		nRet = -2;
		goto exit;
	}
	
	while((nReadLen = fread(szTmpBuf, 1, sizeof(szTmpBuf), pSrcFp)) > 0)
	{
		nWriteLen = fwrite(szTmpBuf, 1, nReadLen, pDstFp);
		if (nWriteLen != nReadLen)
		{
			nRet = -3;
			goto exit;
		}
	}
exit:
	if (pSrcFp != NULL)
		fclose(pSrcFp);
	if (pDstFp != NULL)
		fclose(pDstFp);
	
	if (nRet != 0) 
	{
		DEBUG("%s:%d copy src file:%s to dst file:%s failed, ret:%d\n",  \
				__func__, __LINE__, pSrcFile, pDstFile, nRet);
	} 
	else 
	{
		DEBUG("copy src file:%s to dst file:%s finished\n", pSrcFile, pDstFile);
	}
	return nRet;

}


int ReadInfoPart(int *nFile, DeviceInfoPart *pInfo)
{
	int nRet = 0;
	int nPartNo = 0;

	for (nPartNo = 0; nPartNo < PART_MAX_NUM; nPartNo++) 
	{
		if (strncmp(aPartDefinition[nPartNo].szPartLabel, "flag", strlen(aPartDefinition[nPartNo].szPartLabel)) == 0) 
			break;
	}
	if (nPartNo == PART_MAX_NUM) 
	{
		nRet = -2;
		goto exit;
	}

	if ((*nFile = open(aPartDefinition[nPartNo].szPartMMCBlockDev, O_RDWR)) < 0) 
	{
		nRet = -3;
		goto exit;
	}

	if (read(*nFile, pInfo, sizeof(DeviceInfoPart)) != sizeof(DeviceInfoPart)) 
	{
		nRet = -4;
		goto exit;
	}
	
exit:
	if (nRet != 0) {
		DEBUG("%s:%d read info part error, ret:%d\n", __func__, __LINE__, nRet);
	}
	return nRet;
}

int SetInfoPart(DeviceInfoPart *pInfo)
{	
	int nRet = 0;
	int nFile = -1;
	int i = 0;
	DeviceInfoPart pTmp;
	unsigned int nCalChecksum = 0;
	char *pTmpData = (char *)pInfo;

	nRet = ReadInfoPart(&nFile, &pTmp);
	if (nRet < 0) 
	{
		goto exit;
	}
	
	for (i = 8; i < sizeof(DeviceInfoPart); i++)
	{
		nCalChecksum += (*(unsigned char *)(pTmpData + i)&0xff);
	}
	pInfo->nCheckSum = nCalChecksum;

	lseek(nFile, 0, SEEK_SET);
	if (write(nFile, pInfo, sizeof(DeviceInfoPart)) != sizeof(DeviceInfoPart)) 
	{
		nRet = -5;
		goto exit;
	}

	DEBUG("######pInfo->nUpdateFlag:%d, nBootFlag:%d##########\n", pInfo->nUpdateFlag, pInfo->nBootFlag);
exit:
	if (nRet != 0) 
	{
		DEBUG("%s:%d set_info_part error, ret:%d\n", __func__, __LINE__, nRet);
	}
	if (nFile != -1)
		close(nFile);
	return nRet;
}

int GetInfoPart(DeviceInfoPart *pInfo)
{	
	int nRet = 0;
	int nFile = -1;

	nRet = ReadInfoPart(&nFile, pInfo);
	if (nRet < 0) 
	{
		goto exit;
	}

exit:
	if (nRet != 0) 
	{
		DEBUG("%s:%d get_info_part error, ret:%d\n", __func__, __LINE__, nRet);
	}
	if (nFile != -1)
		close(nFile);
	return nRet;
}

int CheckDeviceInfo(DeviceInfoPart *pInfo)
{
	int i = 0;
	unsigned int nCalChecksum = 0;
	char *pTmpData = (char *)pInfo;
	
	for (i = 8; i < sizeof(DeviceInfoPart); i++)
	{
		nCalChecksum += (*(unsigned char *)(pTmpData + i)&0xff);
	}
	
	if (pInfo->nCheckSum != nCalChecksum)
	{
		DEBUG("check sum is error,nCheckSum:0x%x nCalChecksum:0x%x", pInfo->nCheckSum, nCalChecksum);
		return -1;
	}
	else
	{
		return 0;
	}
}


int MountExt4(const char *pPartName, const char *pPartDir, int nRoFlag)
{
	int nPartNo = 0;
	char nCmd[256];
	
	for (nPartNo = 0; nPartNo < PART_MAX_NUM; nPartNo++) 
	{
		if (strncmp(aPartDefinition[nPartNo].szPartLabel, pPartName, strlen(aPartDefinition[nPartNo].szPartLabel)) == 0)
			break;
	}

	if (nPartNo == PART_MAX_NUM) 
	{
		DEBUG("don't find %s part\n", pPartName);
		return -1;
	}

	memset(nCmd, 0, 256);
	if (nRoFlag == 0)
	{
		sprintf(nCmd, "mount %s %s -o noatime -o barrier=0", aPartDefinition[nPartNo].szPartMMCBlockDev, pPartDir);
	}
	else
	{
		sprintf(nCmd, "mount -o noatime -o ro %s %s", aPartDefinition[nPartNo].szPartMMCBlockDev, pPartDir);
	}
	DEBUG("now %s\n", nCmd);
	MySystem(nCmd);
	
	return 0;
}


int ReadVersion(const char *pName, char *pVersion, char *path)
{	
	FILE *pFp = NULL;
	char *pFind = NULL;
	char *pTmpVersion = NULL;
	char szLine[1024];
	int ret;
	unsigned int nVersionLen;
	if (path == NULL) {
		pFp = fopen("/run/media/mmcblk1p1/update/VERSION_INFO", "r");
	} else {
		pFp = fopen(path, "r");
	}
	
	if (pFp == NULL)
	{
		DEBUG("open /run/media/mmcblk1p1/update/VERSION_INFO failed!\n");
		strncpy(pVersion, "not-find-version", 32);
		ret = -1;
		goto EXIT;
	}
	
	memset(szLine, 0, 1024);
	while (fgets(szLine, 1024, pFp))
	{
		pFind = strstr(szLine, pName);
		if (pFind != NULL)
		{
			break;
		}
		memset(szLine, 0, 1024);
	}
	fclose(pFp);

	if (pFind == NULL)
	{
		DEBUG("do not find %s version in /run/media/mmcblk1p1/update/VERSION_INFO \n", pName);
		strncpy(pVersion, "not-find-version", 32);
		ret = -1;
		goto EXIT;
	}
	else
	{
		pTmpVersion = pFind + 1 + strlen(pName);
		nVersionLen = strlen(pTmpVersion);
		if (nVersionLen > 32) 
		{
			nVersionLen = 32;
		}
		strncpy(pVersion, pTmpVersion, nVersionLen);
		if ((pVersion[nVersionLen - 1] == '\t') || (pVersion[nVersionLen - 1] == '\n'))
		{
			pVersion[nVersionLen - 1] = '\0';
		}
		else
		{
			if (nVersionLen == 32)
			{
				pVersion[nVersionLen - 1] = '\0';
			}
			else
			{
				pVersion[nVersionLen] = '\0';
			}
		}
		DEBUG("read %s version:%s\n", pName, pVersion);
		ret = 0;
	}
	
EXIT:
	pFp = NULL;
	pFind = NULL;
	pTmpVersion = NULL;

	return ret;
}

int GetVersionInfoLine(unsigned int nNum, char *pVersion, unsigned int nSize)
{
	FILE *pFp;
	unsigned int nCount = 0;
	unsigned int nLen = 0;
	char szLine[1024];
	char *pTmpVersion = NULL;
	int nRet = 0;
	
	pFp = fopen("/run/media/mmcblk1p1/update/VERSION_INFO", "r");
	if (pFp == NULL)
	{
		DEBUG("open /run/media/mmcblk1p1/update/VERSION_INFO failed!\n");
		return -1;
	}

	nCount = nNum;
	memset(szLine, 0, 1024);
	while (fgets(szLine, 1024, pFp))
	{
		nCount--;
		if (nCount == 0)
		{
			break;
		}
		memset(szLine, 0, 1024);
	}
	fclose(pFp);

	if (nCount != 0)
	{
		DEBUG("/run/media/mmcblk1p1/update/VERSION_INFO don't have %d line\n", nNum);
		return -1;
	}

	pTmpVersion = szLine;
	nLen = strlen(pTmpVersion);
	if (nLen > nSize) 
	{
		nLen = nSize;
		
	}
	if ((pTmpVersion[nLen - 1] == '\t') || (pTmpVersion[nLen - 1] == '\n'))
	{
		pTmpVersion[nLen - 1] = '\0';
	}
	else
	{
		if (nLen == nSize)
		{
			pTmpVersion[nLen - 1] = '\0';
		}
		else
		{
			pTmpVersion[nLen] = '\0';
		}
	}
	strncpy(pVersion, pTmpVersion, nSize);
	DEBUG("read line:%d version:%s\n", nNum, pVersion);

	return 0;
}

extern void RecordStartTime(void);
extern void RecordEndTime(void);

int MountFileSystem(void)
{
	int nRet = 0;
	int nSDStatus = 0;
	int nRoFlag = 1;
	int nDebugMode = 0;
	DeviceInfoPart tInfo;

	nRet = ReadMMCInfo();
	if (nRet != 0)
	{
		printf("Read mtd failed, nRet = %d\n", nRet);
		return nRet;
	}
	
	nSDStatus = GetSDStatus();
	if (nSDStatus == SD_CARD_MOUNTED)
	{
		return 0;
		#if 0
		if (access("/run/media/mmcblk1p1/update.tar.gz", 0) != -1) {
			MySystem("/run/media/mmcblk1p1/busyboxtest mkfs.ext2 /dev/mmcblk0p5");
			MySystem("/run/media/mmcblk1p1/busyboxtest mkfs.ext2 /dev/mmcblk0p6");
			MySystem("mkdir /app0;mount /dev/mmcblk0p5 /app0");
			MySystem("mkdir /app1;mount /dev/mmcblk0p6 /app1");
		}
		#endif
	}
	else
	{

		nRet = GetInfoPart(&tInfo);
		if (nRet < 0) 
		{
			DEBUG("get info part failed\n");
			return nRet;
		}
		DEBUG("boot version:%s\n", tInfo.szBootVersion);
		if (tInfo.nBootFlag == 1) {
			DEBUG("fs version:%s\n", tInfo.aCoreVer[1].szRootfsVer);
			DEBUG("kernel version:%s\n", tInfo.aCoreVer[1].szKernelVer);
			DEBUG("app version:%s\n", tInfo.aCoreVer[1].szAppVer);
		} else {
			DEBUG("fs version:%s\n", tInfo.aCoreVer[0].szRootfsVer);
			DEBUG("kernel version:%s\n", tInfo.aCoreVer[0].szKernelVer);
			DEBUG("app version:%s\n", tInfo.aCoreVer[0].szAppVer);
		}
		
		VersionInit(&tInfo);

		DEBUG("tInfo.nBootFlag:%d, nUpdateFlag:%d\n", tInfo.nBootFlag, tInfo.nUpdateFlag);
		if (tInfo.nBootFlag == 1)
		{
			//RecordStartTime();
			//MySystem("fsck.fat -a /dev/mmcblk0p6");
			//RecordEndTime();
			MountExt4("app1", "/run/media/mmcblk1p1/", nRoFlag);
			//MountExt4("app0", "/mnt/", nRoFlag);
		}
		else
		{
			//RecordStartTime();
			//MySystem("fsck.fat -a /dev/mmcblk0p5");
			//RecordEndTime();
			MountExt4("app0", "/run/media/mmcblk1p1/", nRoFlag);
			//MountExt4("app1", "/mnt/", nRoFlag);
		}
	}

	return 0;
}

int SaveDdrFile(const char *pFileName, char *pFileBuf, int nFileLen)
{
	FILE *pFd = NULL;
	int nLen = 0;
	int nRet = 0;	
	struct stat fstat;
	
	DEBUG("begin save file %s len %d!\n", pFileName, nFileLen);	
	
	nLen = nFileLen;		
	if ((pFd = fopen(pFileName, "w+")) == NULL)
	{
		DEBUG("create file %s error!\n", pFileName);
		return -1;
	}
	
	while (nLen)
	{	
		if (nLen >= 1024*64)
		{
			if (fwrite(pFileBuf, 1024*64, 1, pFd) == 1)
			{
				pFileBuf += 1024*64;
				nLen -= 1024*64;						
			}		
			else
			{
				DEBUG("write len %d error!\n", 1024*64);	
				fclose(pFd);
				remove(pFileName);
				return 1;
			}
			
		}	
		else
		{
			if (fwrite(pFileBuf, nLen, 1, pFd) == 1)
			{				
				pFileBuf += nLen;
				nLen -= nLen;	
			}
			else
			{
				DEBUG("write len %d error!\n", nLen);	
				fclose(pFd);
				remove(pFileName);
				return 1;	
			}
		}
	}	
	
	fclose(pFd);	
	nRet = stat(pFileName, &fstat);
	if (nRet != 0) 
	{
		DEBUG("get file size failed,remove file %s!\n", pFileName);				
		remove(pFileName);
		return 1;
	}
			
	if (nFileLen == fstat.st_size)
	{
		DEBUG("update %s size is ok!\n", pFileName);		
		return 0;			
	}	
	else
	{
		DEBUG("update %s size is error!\n", pFileName);			
		remove(pFileName);
		return 1;			
	}
}

int FlashLock(void)
{
	int nFd = -1;
	struct erase_info_user einfo;
	
	einfo.start = 0;
	einfo.length = 0x10000;
	nFd = open("/dev/mtd0",  O_RDONLY);
	if (nFd == -1)
	{
		printf("open /dev/mtd0 failed!\n");
		return -1;
	}
	
	ioctl(nFd, MEMLOCK, &einfo);
	close(nFd);
	return 0;
}

int FlashUnlock(void)
{
	int nFd = -1;
	struct erase_info_user einfo;
	
	einfo.start = 0;
	einfo.length = 0x10000;
	nFd = open("/dev/mtd0",  O_RDONLY);
	if (nFd == -1)
	{
		printf("open /dev/mtd0 failed!\n");
		return -1;
	}
	
	ioctl(nFd, MEMUNLOCK, &einfo);
	close(nFd);
	return 0;
}


int DumpInfoPart(DeviceInfoPart *pInfoPart)
{
	int nIndex = 0;
	printf("nParkMarker:0x%x\n", pInfoPart->nParkMarker);
	printf("nUpdateFlag:0x%x\n", pInfoPart->nUpdateFlag);
	printf("nBootFlag:0x%x\n", pInfoPart->nBootFlag);
	printf("szBootVersion:%s\n", pInfoPart->szBootVersion);
	for (nIndex = 0; nIndex < 2; nIndex++)
	{
		printf("szHardwareVer[%d]:%s\n", nIndex, pInfoPart->aCoreVer[nIndex].szHardwareVer);
		printf("szSoftwareVer[%d]:%s\n", nIndex, pInfoPart->aCoreVer[nIndex].szSoftwareVer);
		printf("szDtbVer[%d]:%s\n", nIndex, pInfoPart->aCoreVer[nIndex].szDtbVer);
		printf("szKernelVer[%d]:%s\n", nIndex, pInfoPart->aCoreVer[nIndex].szKernelVer);
		printf("szRootfsVer[%d]:%s\n", nIndex, pInfoPart->aCoreVer[nIndex].szRootfsVer);
		printf("szWeightVer[%d]:%s\n", nIndex, pInfoPart->aCoreVer[nIndex].szWeightVer);
		printf("szFpgaVer[%d]:%s\n", nIndex, pInfoPart->aCoreVer[nIndex].szFpgaVer);
		printf("szMcuVer[%d]:%s\n", nIndex, pInfoPart->aCoreVer[nIndex].szMcuVer);
		printf("szAppVer[%d]:%s\n", nIndex, pInfoPart->aCoreVer[nIndex].szAppVer);
	}
}

/* add pthread_mutex_t function */
void PthreadMutexInit(void)
{
	if (g_pMutexOta == NULL) {
		g_pMutexOta = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
		pthread_mutex_init(g_pMutexOta, NULL);
	}
	if (g_pMutexRqs == NULL) {
		g_pMutexRqs = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
		pthread_mutex_init(g_pMutexRqs, NULL);
	}
}

void PthreadMutexDeinit(void)
{
	if (g_pMutexOta != NULL) {
		pthread_mutex_destroy(g_pMutexOta);
		free(g_pMutexOta);
		g_pMutexOta = NULL;
	}
	if (g_pMutexRqs != NULL) {
		pthread_mutex_destroy(g_pMutexRqs);
		free(g_pMutexRqs);
		g_pMutexRqs = NULL;
	}
}

/* the state use in socket server */
char GetRequestState(void)
{
	char state;
	pthread_mutex_lock(g_pMutexRqs);
	state = requestValve;
	pthread_mutex_unlock(g_pMutexRqs);
	return state;
}

void SetRequestState(char state)
{
	pthread_mutex_lock(g_pMutexRqs);
	requestValve = state;
	pthread_mutex_unlock(g_pMutexRqs);
}

/* communicotion with socket client */
char GetOtaState(void)
{
	char state;
	pthread_mutex_lock(g_pMutexOta);
	state = otaState;
	pthread_mutex_unlock(g_pMutexOta);
	return state;
}

void SetOtaState(char state)
{
	pthread_mutex_lock(g_pMutexOta);
	otaState = state;
	pthread_mutex_unlock(g_pMutexOta);
}

#define MAX_LEN  256
int MySystem(const char *cmd)
{
	char result_buf[MAX_LEN];
	FILE *fp = NULL;
	int ret = 0;

	if (cmd == NULL) {
		DEBUG(" input null cmd\n");
		return 1;
	}
	
	memset(result_buf, 0, MAX_LEN);
	fp = popen(cmd, "r");
	if (fp == NULL) {
		DEBUG("popen fail, system err:%s", strerror(errno));
		return 2;
	}

	while(fgets(result_buf, sizeof(result_buf), fp) != NULL) {
		result_buf[strlen(result_buf)-1] = '\0';
	}
	ret = pclose(fp);
	fp = NULL;
	if (WIFEXITED(ret)) {
        ret = WEXITSTATUS(ret);
		if (ret == 0) {
	        return 0;
	    }
    }

	//DEBUG("system err:%s", result_buf);
	return 3;
	//if (ret != 0) {
	//	DEBUG(" cmd[%s], cmd output[%s] \n", command, result_buf);
	//	DEBUG(" cmd[%s], child process statu[%d], cmd return[%s] \n", command, ret, WEXITSTATUS(ret));
	//}
	//return ret;
}

